import axios from 'axios'
import type { AxiosInstance, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios'
import { ElMessage } from 'element-plus'
import { defaultResponseInterceptors, defaultRequestInterceptors } from './config'
import type { RequestConfig } from './types'

import { useUserStoreWithOut } from '@/store/modules/user'


const router = useRouter()
const userStore = useUserStoreWithOut()

export const BASE_URL = import.meta.env.VITE_API_BASE_URL as string

const abortControllerMap: Map<String, AbortController> = new Map()

const axiosInstance: AxiosInstance = axios.create({
    timeout: 10000,
    baseURL: BASE_URL,
})

axiosInstance.interceptors.request.use((config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
    const controller = new AbortController()
    const url = config.url || ''
    config.signal = controller.signal
    abortControllerMap.set(url, controller)

    return config
})

axiosInstance.interceptors.response.use(
    (response: AxiosResponse) => {
        const url = response.config.url || ''
        abortControllerMap.delete(url)
        // 这里不能做任何处理，否则后面的 interceptors 拿不到完整的上下文了
        return response
    }, 
    (error: AxiosError) => {
        console.log('err:', error)

        if(error.status === 401) {
            userStore.logout()
            router.push('/login')
        } else if(error.status === 403) {
            ElMessage.error("权限不足")
        } else if(error.status === 406) {
            const result = error.response?.data as ApiResult
            ElMessage.error(result.message)
        } else if(error.status === 500) {
            ElMessage.error('后台程序发生错误')
        } else {
            ElMessage.error(error.message)
        }

        return Promise.reject(error)
    }
)

axiosInstance.interceptors.request.use(defaultRequestInterceptors)
axiosInstance.interceptors.response.use(defaultResponseInterceptors as any)

const service = {
    request: (config: RequestConfig) => {
        return new Promise((resolver, reject) => {
            if(config.interceptors?.requestInterceptors) {
                config = config.interceptors.requestInterceptors(config as any)
            }

            axiosInstance.request(config)
                .then((response: AxiosResponse) => {
                    resolver(response)
                })
                .catch((error: AxiosError) => {
                    reject(error)
                })

        })
    },
    cancelRequest: (url: string | string[]) => {
        const urls = Array.isArray(url) ? url : [url]
        for(const _url of urls) {
            const controller = abortControllerMap.get(_url)
            if(controller) {
                controller.abort()
                abortControllerMap.delete(_url)
            }
        }
    },
    cancelAllRequest: () => {
        for(const [_, controller] of abortControllerMap) {
            controller.abort()
        }
        abortControllerMap.clear()
    }
}

export default service